<?php
/**
 * @property  UserModel $mUser
 */

namespace app\index\model;

use app\common\RedisDB;
use app\common\DMutex;
use GatewayClient\Gateway;
use think\log\driver\Socket;

define("DEBUG",true);

class RoomModel extends BaseModel
{
    const LIST_KEY = 'roomlist';
    const PLAYING_KEY = "room_playing_list";
    const INFO_KEY = 'room:';
    const CARDS_KEY = 'CARS:';
    const MAX_POS = 8;
    const DEFAULT_POINT = 10000;
    const MAX_POINT = 4;
    const MAX_STEP = 5;
    const TIMER_DELAY = 16;//后端延迟16s

    const TIMER10=10;
    const TIMER5=5;
    const TIMER3=1;

    //玩家状态
    const STATE_NONE = 0;
    const STATE_READY = 1;
    const STATE_MULTIPLE = 2;
    const STATE_PLAYING = 3;
    const STATE_REPAIR = 4;


    const CARD_SHUANGGUI = 1;
    const CARD_TIANGONG = 2;
    const CARD_SANGUI = 3;
    const CARD_SANTIAO = 4;
    const CARD_TONGHUASHUN = 5;
    const CARD_SHUNZI = 6;
    const CARD_PUTONG = 7;
    const CARD_MUSHI = 8;

    const MULTIPLE_SHUANGGUI = 10;
    const MULTIPLE_SANGUI = 30;
    const MULTIPLE_SANTIAO = 8;
    const MULTIPLE_TONGHUASHUN = 6;
    const MULTIPLE_SHUNZI = 4;
    const MULTIPLE_SANTONGHUA = 3;
    const MULTIPLE_SHUANGTONGHUA = 2;


    private $mUser = null;
    private $id = null;
    private $uid = null;
    private $info = null;
    private $cards = null;

    public function __construct($mUser, $id = null)
    {
        if ($mUser != null) {
            $this->mUser = $mUser;
            $this->uid = $this->mUser->getUid();
        }
        if ($id != null)
            $this->id = $id;
        $this->redis = RedisDB::factory('game');
        $this->cardsredis = RedisDB::factory('cards');
    }

    public function getId()
    {
        return $this->id;
    }

    public function getInfo()
    {
        $this->wtimerdel("gameroom/delroombyurl/roomid/{$this->id}",30*60);
        $this->wtimerset("gameroom/delroombyurl/roomid/{$this->id}",30*60/*+time()*/);
        if ($this->info === null)
        {
            $info = $this->redis->hGetAll(self::INFO_KEY . $this->id);
            if (!$info) {
                throw new Exception('RoomNotFound');
            }

            for ($i = 1; $i <= self::MAX_POS; ++$i) {
                $seatkey = "seat$i";
                if (isset($info[$seatkey])) {
                    $info[$seatkey] = json_decode($info[$seatkey], true);
                }
            }

            $this->info = $info;
        }

        return $this->info;
    }

    public function getInfoEx()
    {
        $info = $this->getInfo();
        $users = array();
        $myseatid = 0;
        for ($i = 1; $i <= self::MAX_POS; ++$i) {
            $seatKey = "seat$i";
            if (empty($info[$seatKey])) {
                continue;
            }

            $seat = $info[$seatKey];
            $mUser = new UserModel($seat['uid']);
            $user = $mUser->getInfo();
            $seat['name'] = $user['nickname'];
            $seat['offline'] = isset($info["exit$i"]);
            $seat['headurl'] = $user['headimgurl'];

            //myself
            if ($seat['uid'] == $this->uid) {
                $myseatid = $seat['seatid'];
                $seat['offline'] = 0;
                if (array_key_exists('cards', $seat))
                    $info['cards'] = $seat['cards'];
            } else {
                if (array_key_exists('cards', $seat) && count($seat['cards']) > 0)
                    foreach ($seat['cards'] as $k => $v) {
                        $seat['cards'][$k] = 0;
                    }
            }

            $users[] = $seat;
        }

        $info['seatid'] = $myseatid;
        $info['users'] = $users;

        //send online state
        $exitkey = "exit{$myseatid}";
        Gateway::$registerAddress = GATEWAYADDRESS;
        if (isset($info[$exitkey])) {
            $this->redis->hDel(self::INFO_KEY . $this->id, $exitkey);
            $json = array('type' => "Room.online", 'data' => array('seatid' => $myseatid));
            Gateway::sendToGroup("game-{$this->id}", json_encode($json));
//            Socket::sendToChannel("game-{$this->id}", "Room", "online", array(
//                'seatid' => $myseatid,
//            ));
        }

        //join


        $cid = Gateway::getClientIdByUid("{$this->uid}");
        if($cid && count($cid)>0)
        Gateway::joinGroup($cid[0], "game-{$this->id}");

        if ($this->getRepairCount($info) == $info['readycount']) {
            $this->setOpenbrand($info);
        }

        return $info;
    }

    public function offline($cid, $seatid)
    {
        Gateway::$registerAddress = GATEWAYADDRESS;

        $this->redis->hSet(self::INFO_KEY . $this->id, "exit{$seatid}", 1);
        $room = $this->getInfo();
        if(DEBUG)
        {
            (new Roomlog())->offlinebefore($room,$seatid);
        }
        $seatkey = "seat$seatid";
        $seat = $room[$seatkey];
        if ($room['started']) {
            $this->setTrust($seatid, true);
        } else {
            $this->mUser->save(array(
                    'roomid' => 0,
                    'seatid' => 0,
                )
            );
            Gateway::leaveGroup($cid, "game-{$this->id}");
//            if ($seat['bready'] == 1) {
//                $this->redis->hIncrBy(self::INFO_KEY . $this->id, 'readycount', -1);
//            }
            $this->redis->hDel(self::INFO_KEY . $this->id, $seatkey);
            $this->redis->hSet(self::INFO_KEY . $this->id, 'seatscount', $this->getSeatsCount());
            $json = array('type' => 'Room.offline', 'data' => array(
                'seatid' => $seatid,
                'leave' => true,
                'trust' => false,
            ));
            if ($room['owner'] == $seat['uid']) {
                if ($room['seatscount']-1 == 0) {
                    //$this->redis->del(self::INFO_KEY.$this->id);
                } else {

                }
            }
        }

        if(DEBUG)
        {
            $this->info=null;
            $room = $this->getInfo();
            (new Roomlog())->offlineafter($room);
        }

        Gateway::sendToGroup("game-{$this->id}", json_encode($json));
    }

    public function create($round, $type, $jcard, $multiples)
    {
        $this->wtimerset("gameroom/delroombyurl/roomid/{$this->id}",30*60/*+time()*/);
        //随机生成房间号
        do {
            $id = mt_rand(100000, 999999);
            $ret = $this->redis->hSetNx(self::LIST_KEY, $id, time());
            if (!$ret) {
                continue;
            }

            break;
        } while (true);

        $uid = $this->mUser->getUid();
        $user = $this->mUser->getinfo();
        $seat = array(
            'uid' => $uid,
            'bovertime' => false,
            'seatid' => 1,
            'sex' => $user['sex'],
            'joinround'=>1,
            'state' => self::STATE_NONE,
            'bstart'=>0,
            'bready'=>0,
            'bmultiple'=>0,
            'brepair'=>0,
            'bover'=>0,
            'scores' => 0,
            'ready' => 0,
            'multiples' => 0,
            'trust' => 0,
            'carry' => 0,
            'zhuang' => 0,
            'headerurl' => $user['headimgurl'],
            'name' => $user['nickname'],
        );
        $this->id = $id;
        $this->info = array(
            'id' => $id,
            'owner' => $uid,//房主
            'time' => time(),//创建时间
            'started' => 0,
            'state' => 0,//状态
            'seatscount' => 1,
            'readycount' => 0,
            'multiplescount' => 0,
            'repaircount' => 0,
            "disbandcount" => 0,
            'currentround' => 1,//当前局数
            'round' => $round,//局数
            'type' => $type,
            'jcard' => $jcard,
            'joker' => null,
            'multiples' => $multiples,
            'seat1' => json_encode($seat),
            'zhuangid' => 0,
            'current' => 1,
        );
        $data["owneruid"]=$uid;
        $data['roomid']=$id;
        $data['createtime']=date("Y-m-d H:i:s",time());
        $data['type']=$type;
        $data['round']=$round;
        $data['bjcard']=$jcard;
        $data['multiples']=$multiples;
        $this->info["sid"]= db('room')->insertGetId($data);
        $this->redis->hMSet(self::INFO_KEY . $id, $this->info);
        $this->mUser->save(array(
            'roomid' => $id,
            'seatid' => 1,
        ));
        if(DEBUG)
        {
            $this->info=null;
            $this->getInfo();
            (new Roomlog())->createroom($this->info);
        }
        return array(
            'roomid' => $id,
            'seatid' => 1,
        );
    }

    private function setTimer()
    {
        $this->redis->zadd(self::PLAYING_KEY, time() + self::TIMER_DELAY, $this->id);
    }

    private function delTimer()
    {
        $this->redis->zrem(self::PLAYING_KEY, $this->id);
    }

    public function disband()
    {
        $uid = $this->mUser->getUid();
        $user = $this->mUser->getinfo();
        $room = $this->getInfo();
        if(DEBUG)
        {
            (new Roomlog())->disbandbefore($room,$user['seatid']);
        }
        $room['disbandcount'] = 1;

        Gateway::$registerAddress = GATEWAYADDRESS;
        $json = array('type' => 'Room.disband', 'data' => $user['nickname']);
        Gateway::sendToGroup("game-{$user['roomid']}", json_encode($json), Gateway::getClientIdByUid($uid));

        $data['roomid']=$room['sid'];
        $data['actiontype']=3;
        $data['time']=date("Y-m-d H:i:s",time());
        $data['uid']=$uid;

        $did = db('roomaction')->insertGetId($data);

        $this->redis->hMset(self::INFO_KEY . $this->getId(),array( "disbandcount"=>1,'disbandid'=>$did));

        if(DEBUG)
        {
            $this->info=null;
            $room=$this->getInfo();
            (new Roomlog())->disbandafter($room,$user['seatid']);
        }

        for ($i = 1; $i <= self::MAX_POS; ++$i) {
            $seatkey = "seat$i";
            if (!isset($room[$seatkey]) || $i==$user['seatid']) {
                continue;
            }
            $seat = $room[$seatkey];
            if ($seat['trust']) {
                $this->info = null;
                $room = $this->getInfo();
                $this->setdodisband($room, $i, true);
            }
        }



        return true;
    }

    public function setTrustReady()
    {
        $room = $this->getInfo();
        for ($i = 1; $i <= self::MAX_POS; ++$i) {
            $seatkey = "seat$i";
            if (!isset($room[$seatkey])) {
                continue;
            }
            $seat = $room[$seatkey];
            if ($seat['trust'] && $seat['state'] == self::STATE_NONE) {
                $u = new UserModel($seat['uid']);
                $u = $u->getInfo();
                $this->ready(false, $u);
            }
        }
        return true;
    }

    public function setTrustMultiple()
    {
        $room = $this->getInfo();
        for ($i = 1; $i <= self::MAX_POS; ++$i) {
            $seatkey = "seat$i";
            if (!isset($room[$seatkey])) {
                continue;
            }
            $seat = $room[$seatkey];
            if ($seat['trust'] && $seat['state'] == self::STATE_READY) {
                $this->setmultiple($room, $i, 1);
            }
        }
        return true;
    }


    public function dodisband($disband)
    {
        $room = $this->getInfo();
        $user = $this->mUser->getInfo();
        $this->setdodisband($room, $user['seatid'], $disband);
    }

    public function setdodisband($room, $i, $disband)
    {
        if(DEBUG)
        {
            (new Roomlog())->dodisbandbefore($room,$i);
        }
        $uid = $room["seat$i"]['uid'];
        if ($disband == 0) {
            //不同意解散
            Gateway::$registerAddress = GATEWAYADDRESS;
            $json = array('type' => 'Room.dodisband', 'data' => array('seatid' => $i, 'agree' => 0));
            Gateway::sendToGroup("game-{$room['id']}", json_encode($json), Gateway::getClientIdByUid($uid));

            db('roomaction')->where("id={$room['disbandid']}")->update(['result'=>0]);

            return true;
        }
        $this->redis->hIncrBy(self::INFO_KEY . $this->getId(), "disbandcount", 1);
        $this->info = null;
        $room = $this->getInfo();

        if(DEBUG)
        {
            (new Roomlog())->dodisbandafter($room,$i);
        }

        Gateway::$registerAddress = GATEWAYADDRESS;
        $json = array('type' => 'Room.dodisband', 'data' => array('seatid' => $i, 'agree' => 1, 'disbandcount' => $room['disbandcount']));
        Gateway::sendToGroup("game-{$room['id']}", json_encode($json), Gateway::getClientIdByUid($uid));

        if ($room['disbandcount'] == $room['seatscount']) {
            $this->delroom($room);
            db('roomaction')->where("id={$room['disbandid']}")->update(['result'=>0]);
        }
        return true;
    }

    public function delroom()
    {
        if ($this->info === null) {
            $info = $this->redis->hGetAll(self::INFO_KEY . $this->id);
            if (!$info) {
                throw new Exception('RoomNotFound');
            }

            for ($i = 1; $i <= self::MAX_POS; ++$i) {
                $seatkey = "seat$i";
                if (isset($info[$seatkey])) {
                    $info[$seatkey] = json_decode($info[$seatkey], true);
                }
            }

            $this->info = $info;
        }
        $room=$this->info;
        $data = array();
        $data['roomid'] = $room['sid'];
        $data['roomtype'] = $room['type'];
        $data['roomround'] = $room['round'];
        $data['time'] = date("Y-m-d H:i:s", time());
        //解散房间
        for ($i = 1; $i <= self::MAX_POS; ++$i) {
            $seatkey = "seat$i";

            if (empty($room[$seatkey])) {
                continue;
            }

            $seat = $room[$seatkey];

            $data["openid$i"] = $seat['uid'];
            $data["headerurl$i"] = $seat['headerurl'];
            $data["seatid$i"] = $seat['seatid'];
            $data["scores$i"] = $seat['scores'];
            $data["name$i"] = $seat['name'];
            $mUser = new UserModel($seat['uid']);
            $mUser->save(array(
                'roomid' => 0,
                'seatid' => 0,
            ));
        }
        db('room')->where("id={$room['sid']}")->update(['disbandtime'=>date("Y-m-d H:i:s",time())]);
        $id = db('records')->insertGetId($data);
        $data['id']=$id;
        $json = array('type' => 'Room.showBattle', 'data' => $data);
        Gateway::$registerAddress = GATEWAYADDRESS;
        Gateway::sendToGroup("game-{$room['id']}", json_encode($json));
        for ($i = 1; $i <= self::MAX_POS; ++$i) {
            $seatkey = "seat$i";

            if (empty($room[$seatkey])) {
                continue;
            }

            $seat = $room[$seatkey];
            $cids =Gateway::getClientIdByUid($seat['uid']);
            foreach($cids as $cid)
            Gateway::leaveGroup($cid, "game-{$this->id}");
        }

        //显示战绩，删除房间
        $this->redis->del(self::INFO_KEY . $this->id);
        $this->wtimerdelroom();//"gameroom/delroombyurl/roomid/{$this->id}");
        return true;
    }

    public function updatescores()
    {
        $user = $this->mUser->getinfo();
        $room = $this->getInfo();
        for ($i = 1; $i <= self::MAX_POS; ++$i) {
            $seatkey = "seat$i";

            if (empty($room[$seatkey])) {
                continue;
            }

            $seat = $room[$seatkey];

            $data["openid$i"] = $seat['uid'];
            $data["headerurl$i"] = $seat['headerurl'];
            $data["seatid$i"] = $seat['seatid'];
            $data["scores$i"] = $seat['scores'];
            $data["name$i"] = $seat['name'];
        }
        $json = array('type' => 'Room.showBattle', 'data' => $data);
        Gateway::sendToUid($this->uid, json_encode($json));
    }

    public function outroom($i)
    {
        $room = $this->getInfo();
        if(DEBUG)
        {
            (new Roomlog())->outroombefore($room,$i);
        }

        Gateway::$registerAddress = GATEWAYADDRESS;
        $json = array('type' => 'Room.outroom', 'data' => array('seatid' => $i, 'leave' => false));
        if ($room['started'] == 0 || $room["seat$i"]['bstart']==0) {
            $seatkey = "seat{$i}";
            $seat=$room[$seatkey];
//            if ($seat['state'] == self::STATE_READY) {
//                $this->redis->hIncrBy(self::INFO_KEY . $this->id, 'readycount', -1);
//            }
            $u = new UserModel($room[$seatkey]['uid']);
            $u->save(array('roomid' => 0, 'seatid' => 0));
            $this->redis->hDel(self::INFO_KEY . $this->id, "seat{$i}");
            if($room['started'] == 0 )
            $this->redis->hSet(self::INFO_KEY . $this->id, 'seatscount', $this->getSeatsCount());
            $json = array('type' => 'Room.outroom', 'data' => array('seatid' => $i, 'leave' => true));
            Gateway::sendToGroup("game-{$this->id}", json_encode($json));
        } else if ($room['started'] == 1) {
            $seatkey = "seat{$i}";
            $seat = $room[$seatkey];
            $seat["trust"] = true;
            $this->redis->hSet(self::INFO_KEY . $room['id'], $seatkey, json_encode($seat));
            $json = array('type' => 'Room.outroom', 'data' => array('seatid' => $i, 'leave' => false));
            Gateway::sendToUid($room[$seatkey]['uid'], json_encode($json));
        }
        Gateway::leaveGroup(Gateway::getClientIdByUid($room[$seatkey]['uid'])[0], "game-{$this->id}");
        $this->info=null;
        $room=$this->getInfo();
        if(DEBUG)
        {
            (new Roomlog())->outroomafter($room);
        }
        if($room['seatscount']==0)
        {
            //$this->redis->del(self::INFO_KEY.$this->id);
        }
        return true;
    }

    public function setOvertimer($i)
    {
        $this->info = null;
        $room = $this->getInfo();
        $seat = $room["seat$i"];
        $seat['bovertime'] = true;
        $this->redis->hSet(self::INFO_KEY . $this->id, "seat$i", json_encode($seat));
        Gateway::$registerAddress = GATEWAYADDRESS;
        Gateway::sendToGroup("game-{$this->id}", json_encode(array('type' => "Room.overtime", 'data' => array('seatid' => $i, 'state' => $seat['state']))));
    }

    public function join()
    {
        $uid = $this->mUser->getUid();
        $info = $this->getInfo();
        if(DEBUG)
        {
            (new Roomlog())->joinroombefore($info,$uid,$this->mUser->getInfo()['nickname']);
        }
        $pos = 0;
        for ($i = 1; $i <= self::MAX_POS; ++$i) {
            $seatKey = "seat$i";
            if (!empty($info[$seatKey])) {
                if($info[$seatKey]['uid']==$uid)
                {
                    $user = $this->mUser->getInfo();
                    $data = array(
                        'uid' => $uid,
                        'seatid' => $i,
                        'state' => self::STATE_NONE,
                        'name' => $user['nickname'],
                        'headurl' => $user['headimgurl'],
                    );
                    Gateway::$registerAddress = GATEWAYADDRESS;
                    Gateway::sendToGroup("game-{$this->id}", json_encode(array('type' => 'Room.join', 'data' => $data)));
                    $cid = Gateway::getClientIdByUid($uid);
                    Gateway::joinGroup($cid[0], "game-{$this->id}");
                    return true;
                }
                continue;
            }

            if (!$this->redis->hSetNx(self::INFO_KEY . $this->id, $seatKey, $uid)) {
                continue;
            }

            $pos = $i;
            break;
        }
        if ($pos) {
            $user = $this->mUser->getInfo();
            $seat = array(
                'uid' => $uid,
                'bovertime' => false,
                'seatid' => $pos,
                'sex' => $user['sex'],
                'joinround'=>$info['currentround'],
                'state' => self::STATE_NONE,
                'bstart'=>0,
                'bready'=>0,
                'bmultiple'=>0,
                'brepair'=>0,
                'bover'=>0,
                'zhuang'=>0,
                'scores' => 0,
                'multiples' => 0,
                'trust' => 0,
                'cards' => null,
                'carry' => 0,
                'headerurl' => $user['headimgurl'],
                'name' => $user['nickname'],
            );
            $this->redis->hSet(self::INFO_KEY . $this->id, $seatKey, json_encode($seat));
            $this->mUser->save(array(
                'roomid' => $this->id,
                'seatid' => $pos,
            ));
            if(!$info['started'])
                $this->redis->hSet(self::INFO_KEY . $this->id, 'seatscount', $this->getSeatsCount());
            //notify
            $data = array(
                'uid' => $uid,
                'seatid' => $pos,
                'state' => self::STATE_NONE,
                'name' => $user['nickname'],
                'headurl' => $user['headimgurl'],
            );
            Gateway::$registerAddress = GATEWAYADDRESS;
            Gateway::sendToGroup("game-{$this->id}", json_encode(array('type' => 'Room.join', 'data' => $data)));
            $cid = Gateway::getClientIdByUid($uid);
            Gateway::joinGroup($cid[0], "game-{$this->id}");
        } else {
            $this->_error = 'PositionLess';
            return false;
        }
        if(DEBUG) {
            $this->info=null;
            $this->info=$this->getInfo();
            (new Roomlog())->joinroomafter($this->info, $pos);
        }
        return array(
            'roomid' => $this->id,
            'seatid' => $pos,
        );
    }

    public function bstart($user = null)
    {
        Gateway::$registerAddress = GATEWAYADDRESS;
        $this->info = null;
        $room = $this->getInfo();

        if ($user == null)
            $user = $this->mUser->getInfo();
        $seatid = $user['seatid'];
        if(DEBUG)
        {
            (new Roomlog())->startbefore($room,$seatid);
        }
        $seat = $room["seat$seatid"];
        $seat['bstart']=1;
        $this->redis->hMset(self::INFO_KEY . $this->id,array("seat$seatid"=>json_encode($seat),'seatscount'=> $this->getSeatsCount()));

        if(DEBUG)
        {
            $this->info = null;
            $room = $this->getInfo();
            (new Roomlog())->startafter($room,$seatid);
        }

        Gateway::sendToUid($seat['uid'],json_encode(array('type'=>'Room.bstart','data'=>array('seatid'=>$seatid,'bstart'=>1,'state'=>$room['state']))));
        return true;
    }

    public function ready($zhuang = false, $user = null)
    {
        Gateway::$registerAddress = GATEWAYADDRESS;
        $room = $this->getInfo();

        if ($user == null)
            $user = $this->mUser->getInfo();
        $seatid = $user['seatid'];
        if (DEBUG) {
            (new Roomlog())->readybefore($room, $seatid);
        }
        if($room['state']>0)return;
        if ($this->setReady($room, $seatid, $zhuang)) {
            $this->info = null;
            $room = $this->getInfo();
            $json = array('type' => 'Room.ready', 'data' => $room["seat{$seatid}"]);
            Gateway::sendToGroup("game-{$this->id}", json_encode($json));
        } else {
            print_r($this->_error);
        }
        $readycount = $this->getReadyCount($room);
        if (DEBUG) {
            (new Roomlog())->readyafter($this->getInfo(), $seatid);
        }
        if ($readycount > 1 && $room['seatscount'] == $readycount) {
            $this->info = null;
            $room = $this->getInfo();
            $this->setStart($room);
        } else if ($room['readycount'] >= 2) {
//            $owner = (new UserModel($room['owner']))->getInfo();
//            if (isset($room["seat{$owner['seatid']}"]) && $room["seat{$owner['seatid']}"]['uid']==$room['owner'] && $room["seat{$owner['seatid']}"]['bready']) {
                $json = array('type' => 'Room.wready', 'data' => array());
                Gateway::sendToGroup("game-{$this->id}", json_encode($json));
                $this->wtimerset("gameroom/updatestate/roomid/{$room['id']}/started/0/state/0/round/{$room['currentround']}", self::TIMER10 /*+time()*/);
//            }
        }
        return true;
    }

    public function onmultiple($multiple)
    {
        Gateway::$registerAddress = GATEWAYADDRESS;

        $this->info = null;
        $room = $this->getInfo();
        $user = $this->mUser->getInfo();

        if (!$this->setmultiple($room, $user['seatid'], $multiple)) {
            return false;
        }

        return true;
    }

    public function balance($cards1, $cards2)
    {

        $cardtype1 = $this->getCardType($cards1);
        $type1 = $cardtype1['type'];
        $point1 = $cardtype1['point'];
        $m1 = $cardtype1['multiple'];
        $cardtype2 = $this->getCardType($cards2);
        $type2 = $cardtype2['type'];
        $point2 = $cardtype2['point'];
        $m2 = $cardtype2['multiple'];
        switch ($type1) {
            case self::CARD_SHUANGGUI:
                if ($type2 == self::CARD_MUSHI && count($cards2)==3) {
                    return -$m1;
                }
                else if($type2==self::CARD_SHUANGGUI)
                    return 0;
                else {
                    if ($type1==$type2) {
                        return $m1 > $m2 ? $m1 : -$m2;
                    }else {
                        return $type1<$type2?$m1:-$m2;
                    }
                }
                break;
            case self::CARD_MUSHI:
                if(count($cards1)==3 && $type2==self::CARD_SHUANGGUI)
                {
                    return $m2;
                }
                else{
                    if ($type1==$type2) {
                        if ($m1 == $m2)
                            return 0;
                        else
                            return $m1 > $m2 ? $m1 : -$m2;
                    }
                    else {
                        return $type1<$type2?$m1:-$m2;
                    }
                }
                break;
            default:
                if ($type1==$type2) {
                    if ($type2 == self::CARD_PUTONG || $type2==self::CARD_TIANGONG) {
                        if($point1==$point2) {
                            if ($m1 == $m2)
                                return 0;
                            else
                                return $m1 > $m2 ? $m1 : -$m2;
                        }
                        else
                            return $point1 > $point2 ? $m1 : -$m2;
                    }
                    else return 0;
                }
                else {
                    return $type1<$type2?$m1:-$m2;
                }
        }
    }

    public function getCardType($cards)
    {
        $point = 0;
        $type = 0;
        $multiple = 1;
        if (count($cards) == 2) {
            $color1 = floor($cards[0] / 100);
            $number1 = $cards[0] % 100;
            $color2 = floor($cards[1] / 100);
            $number2 = $cards[1] % 100;

            if ($color1 == 5 && $color2 == 5) {
                $type = self::CARD_SHUANGGUI;
                $multiple = self::MULTIPLE_SHUANGGUI;
            } else {
                if ($color1 == 5 || $number1 > 9) $number1 = 0;
                if ($color2 == 5 || $number2 > 9) $number2 = 0;
                $number = $number1 + $number2;
                $number = $number % 10;
                if ($color1 == 5 || $color2 == 5 || ($color1 == $color2))
                    $multiple = self::MULTIPLE_SHUANGTONGHUA;
                if ($number == 8 || $number == 9) {
                    $type = self::CARD_TIANGONG;
                    $point = $number;
                    if ($color1 == $color2 || $number2 == $number1) $multiple = self::MULTIPLE_SHUANGTONGHUA;
                } else if ($number % 10 == 0) {
                    $type = self::CARD_MUSHI;
                    $point = 0;
                    if ($color1 == $color2 || $number2 == $number1) $multiple = self::MULTIPLE_SHUANGTONGHUA;
                } else {
                    $type = self::CARD_PUTONG;
                    $point = ($number1 + $number2) % 10;
                    if ($color1 == $color2 || $number2 == $number1) {
                        $multiple = self::MULTIPLE_SHUANGTONGHUA;
                    }
                }
            }
        } else if (count($cards) == 3) {
            $color1 = floor($cards[0] / 100);
            $number1 = $cards[0] % 100;
            $color2 = floor($cards[1] / 100);
            $number2 = $cards[1] % 100;
            $color3 = floor($cards[2] / 100);
            $number3 = $cards[2] % 100;
            $jcardcount = 0;
            if ($color1 == 5)
                $jcardcount++;
            if ($color2 == 5)
                $jcardcount++;
            if ($color3 == 5)
                $jcardcount++;
            if ($jcardcount == 3) {
                $type = self::CARD_SANGUI;
                $multiple = self::MULTIPLE_SANGUI;
            } else if ($jcardcount == 0) {
                if ($number1 == $number2 && $number2 == $number3) {
                    $type = self::CARD_SANTIAO;
                    $multiple = self::MULTIPLE_SANTIAO;
                } else {
                    $max = max(max($number1, $number2), $number3);
                    $min = min(min($number1, $number2), $number3);

                    if (($max - $min == 2 && $max * 3 == $number3 + $number2 + $number1 + 3) || ($max - $min == 12 && ($number1 + $number3 + $number2 == 26 || $number1 + $number2 + $number3 == 16))) {
                        if ($color1 == $color2 && $color2 == $color3) {
                            $type = self::CARD_TONGHUASHUN;
                            $multiple = self::MULTIPLE_TONGHUASHUN;
                        } else {
                            $type = self::CARD_SHUNZI;
                            $multiple = self::MULTIPLE_SHUNZI;
                        }
                    } else {
                        if ($number1 > 9) $number1 = 0;
                        if ($number2 > 9) $number2 = 0;
                        if ($number3 > 9) $number3 = 0;
                        if (($number1 + $number2 + $number3) % 10 == 0) {
                            $type = self::CARD_MUSHI;
                        } else {
                            $type = self::CARD_PUTONG;
                            $point = ($number1 + $number2 + $number3) % 10;
                        }
                        if ($color1 == $color2 && $color2 == $color3) {
                            $multiple = self::MULTIPLE_SANTONGHUA;
                        }
                    }
                }
            } else if ($jcardcount == 2) {
                $type = self::CARD_SANTIAO;
                $multiple = self::MULTIPLE_SANTIAO;
            } else if ($jcardcount == 1) {
                $c1 = $color1 == 5 ? $cards[1] : $cards[0];
                $c2 = $color3 == 5 ? $cards[1] : $cards[2];
                $cn1 = $c1 % 100;
                $cn2 = $c2 % 100;
                $cc1 = floor($c1 / 100);
                $cc2 = floor($c2 / 100);
                if ($cn1 == $cn2) {
                    $type = self::CARD_SANTIAO;
                    $multiple = self::MULTIPLE_SANTIAO;
                } else if (($cn1 < $cn2 && $cn1 + 3 > $cn2) || ($cn2 < $cn1 && $cn2 + 3 > $cn1) || ($cn1 < $cn2 && $cn2 - 10 > $cn1) || ($cn2 < $cn1 && $cn1 - 10 > $cn2)) {

                    if ($cc1 == $cc2) {
                        $type = self::CARD_TONGHUASHUN;
                        $multiple = self::MULTIPLE_TONGHUASHUN;
                    } else {
                        $type = self::CARD_SHUNZI;
                        $multiple = self::MULTIPLE_SHUNZI;
                    }
                } else {
                    if ($cn1 > 9) $cn1 = 0;
                    if ($cn2 > 9) $cn2 = 0;
                    $point = ($cn1 + $cn2) % 10;
                    if ($point == 0) {
                        $type = self::CARD_MUSHI;
                        if ($cc1 == $cc2) {
                            if ($cc1 == $cc2) {
                                $multiple = self::MULTIPLE_SANTONGHUA;
                            }
                        }
                    } else {
                        $type = self::CARD_PUTONG;
                        if ($cc1 == $cc2) {
                            $multiple = self::MULTIPLE_SANTONGHUA;
                        }
                    }
                }
            }
        } else {
            $this->_error = 'getCardTypeFailed';
            $type = false;
        }

        return array('type' => $type, 'point' => $point, 'multiple' => $multiple, 'scores' => 0);

    }

    public function repair($brepair = true, $checktrust = false)
    {

        $room = $this->getInfo();

       
        $user = $this->mUser->getInfo();

        if ($checktrust) {
            if (!$room["seat{$user['seatid']}"]['trust']) {
                return true;
            }
        }

        if (!$this->setRepair($room, $user['seatid'], $brepair)) {
            print_r($this->_error);
            //发生错误
        }
        return true;

    }

    public function giveup()
    {
        $this->_error = 'GiveupFailed';

        $room = $this->getInfo();
        if (!$room['state']) {
            return false;
        }

        $user = $this->mUser->getInfo();
        if ($user['seatid'] != $room['current']) {
            return false;
        }

        $seatkey = "seat" . $user['seatid'];
        $seat = $room[$seatkey];
        if (!empty($seat['giveup'])) {
            return false;
        }

        //加锁
        $this->lock();

        //数据更新
        $seat['giveup'] = 1;
        $seat['state'] = self::STATE_NONE;
        $room[$seatkey] = $seat;
        $room['current'] = $this->getNext($room);
        $this->redis->hMSet(self::INFO_KEY . $this->id, array(
            'current' => $room['current'],
            $seatkey => json_encode($seat),
        ));

        //通知
        Socket::sendToChannel("game-{$this->id}", "Room", "giveup", array(
            'seatid' => $user['seatid'],
            'current' => $room['current'],
        ));

        //更新定时器
        $this->setTimer();

        //游戏结束
        if (!$room['current']) {
            $this->gameOver($room);
        }

        //解锁
        $this->unlock();

        return true;
    }

    public function pk($seatid)
    {
        $this->_error = 'PkFailed';

        $room = $this->getInfo();
        if (!$room['state']) {
            return false;
        }

        $user = $this->mUser->getInfo();
        if ($user['seatid'] != $room['current']) {
            return false;
        }

        if ($user['seatid'] == $seatid) {
            return false;
        }

        $seatkey = "seat" . $user['seatid'];
        $seatkey2 = "seat" . $seatid;
        $seat = $room[$seatkey];
        $seat2 = $room[$seatkey2];
        if ($seat2['state'] != self::STATE_PLAYING) {
            return false;
        }

        //加锁
        $this->lock();

        //比牌
        $win = $this->compareCard($seat['cards'], $seat2['cards']);

        //比牌消耗
        $multi = empty($seat['look']) ? 1 : 2;
        $addpoint = ($room['point'] * $multi);
        $seat['point'] += $addpoint;
        $room['total'] += $addpoint;
        $room['coins'][] = $addpoint;

        //数据更新
        $sets = array();
        if ($win == 1) {
            $seat2['lose'] = 1;
            $seat2['state'] = self::STATE_NONE;
            $sets[$seatkey] = json_encode($seat);
            $sets[$seatkey2] = json_encode($seat2);
        } else {
            $seat['lose'] = 1;
            $seat['state'] = self::STATE_NONE;
            $sets[$seatkey] = json_encode($seat);
        }
        $room[$seatkey] = $seat;
        $room[$seatkey2] = $seat2;
        $room['current'] = $this->getNext($room);
        $sets['total'] = $room['total'];
        $sets['current'] = $room['current'];
        $sets['coins'] = json_encode($room['coins']);
        $this->redis->hMSet(self::INFO_KEY . $this->id, $sets);

        //更新定时器
        $this->setTimer();

        //通知
        Socket::sendToChannel("game-{$this->id}", "Room", "pk", array(
            'seatid' => $user['seatid'],
            'pkid' => $seatid,
            'total' => $room['total'],
            'point' => $room['point'],
            'user_point' => $seat['point'],
            'add_point' => $addpoint,
            'loseid' => $win == 1 ? $seatid : $user['seatid'],
            'current' => $room['current'],
        ));

        //游戏结束
        if (!$room['current']) {
            $this->gameOver($room);
        }

        //解锁
        $this->unlock();

        return true;
    }

    public function nextRound($carry)
    {
        $user = $this->mUser->getInfo();
        $room = $this->getInfo();
        $data = array();

        $seatkey = "seat" . $user['seatid'];

        $seat = $room[$seatkey];

        $seat['carry'] = $carry;

        $this->redis->hSet(self::INFO_KEY . $room['id'], $seatkey, json_encode($seat));

        $balance = $room['currentround'] > $room['round'];
        Gateway::$registerAddress = GATEWAYADDRESS;
        $json = array('type' => 'Room.over', 'data' => array(
            'currentround' => $room['currentround'],
            'balance' => $balance,
        ));
        Gateway::sendToUid($user['openid'], json_encode($json));
        $this->ready();
        return true;
    }

    /**
     * 游戏结束
     * @param array $room
     */
    private function gameOver($room)
    {
        $data = array();
        $data2 = array();
        $room['currentround'] += 1;
        $balance = ($room['currentround'] >= $room['round']) ? 1 : 0;
        $lastMaxIndex = -1;
        for ($i = 1; $i <= self::MAX_POS; ++$i) {
            $seatkey = "seat$i";

            if (empty($room[$seatkey])) {
                continue;
            }

            $seat = $room[$seatkey];


            //update seat
            $seat['state'] = self::STATE_NONE;
            $seat['point'] = 0;
            $this->redis->hSet(self::INFO_KEY . $room['id'], $seatkey, json_encode($seat));

            //update user
            $mUser = new UserModel($seat['uid']);
            if ($balance) {
                $mUser->save(array(
                    'roomid' => 0,
                    'seatid' => 0,
                ));

                $king = false;
                if ($lastMaxIndex == -1) {
                    $lastMaxIndex = count($data2);
                    $king = true;
                }

                $data2[] = array(
                    'seatid' => $i,
                );
            }

            $data[] = array(
                'seatid' => $i,
            );
        }

        //关闭
        if ($balance) {
            $this->redis->del(self::INFO_KEY . $room['id']);
        } else {
            $this->redis->hMSet(self::INFO_KEY . $room['id'], array(
                'state' => 0,
                'currentround' => $room['currentround'],
            ));
        }

        //删除定时器
        $this->delTimer();

        Gateway::$registerAddress = GATEWAYADDRESS;
        $json = array('type' => 'Room.over', 'data' => array(
            'currentround' => $room['currentround'],
            'balance' => $balance,
            'list' => $data,
            'list2' => $data2,
        ));
        Gateway::sendToGroup("game-{$this->id}", json_encode($json));


    }

    /**
     * 操作加锁
     */
    private function lock()
    {
        $lockName = "oplock-{$this->id}-{$this->uid}";
        if (!DMutex::lock($lockName)) {
            sleep(0.1);
            $this->lock();
            //throw new Exception('Locked');
        }
    }

    /**
     * 操作解锁
     */
    private function unlock()
    {
        $lockName = "oplock-{$this->id}-{$this->uid}";
        DMutex::unlock($lockName);
    }

    /**
     * 设置玩家玩准备状态
     * @param $room
     * @param $seatid
     * @param bool $zhuang
     * @return bool 失败时候，会返回错误信息
     * @throws Exception
     */
    private function setReady($room, $seatid, $zhuang = false)
    {
        $update = array();
        if (!$room || !$seatid) {
            return false;
        }

        $seatkey = "seat$seatid";
        $seat = $room[$seatkey];
        if (!$seat) {
            $this->_error = "have not $seatkey";
            return false;
        }

        if ($seat['bready'] || $seat['state']>0) {
            $this->_error = "$seatkey readyed";
            return false;
        }
        $this->lock();
        $seat['bstart']=1;
        $seat['state'] = self::STATE_READY;
        $seat['bready']=1;
        if ($zhuang) {
            if ($seatid == $room['owner'] || $room['zhuangid'] == 0) {
                $update['zhuangid'] = $seatid;
                $this->info['zhuangid']=$seatid;
                $seat['zhuang'] = $zhuang;
            }
        }
        $update[$seatkey] = json_encode($seat);
        $this->info[$seatkey]=$seat;
        $this->redis->hMSet(self::INFO_KEY . $this->id, $update);
        $this->unlock();
        return true;
    }

    private function getReadyCount($room)
    {
        $this->info=null;
        $room=$this->getInfo();
        $count = 0;
        for ($i = 1; $i <= self::MAX_POS; ++$i) {
            if (!isset($room["seat$i"])) {
                continue;
            }
            $seat = $room["seat$i"];
            if ($seat['bready'])
                ++$count;
        }
        return $count;
    }

    private function getSeatsCount()
    {
        $this->info=null;
        $room=$this->getInfo();
        $count = 0;
        for ($i = 1; $i <= self::MAX_POS; ++$i) {
            if (!isset($room["seat$i"])) {
                continue;
            }
            ++$count;
        }
        return $count;
    }

    public function getMultiplesCount($room)
    {
        $this->info=null;
        $room=$this->getInfo();
        $count = 0;
        for ($i = 1; $i <= self::MAX_POS; ++$i) {
            if (!isset($room["seat$i"])) {
                continue;
            }
            $seat = $room["seat$i"];
            if ($seat['bmultiple'])
                ++$count;
        }

        return $count;
    }

    public function getRepairCount($room)
    {
        $this->info=null;
        $room=$this->getInfo();
        $count = 0;
        for ($i = 1; $i <= self::MAX_POS; ++$i) {
            if (!isset($room["seat$i"])) {
                continue;
            }
            $seat = $room["seat$i"];
            if ($seat['brepair'])
                ++$count;
        }
        return $count;
    }

    /**
     * 补牌操作
     * @param $room
     * @param $i
     * @param $brepair
     * @return bool
     * @throws Exception
     * @throws \Exception
     */
    private function setRepair($room, $i, $brepair)
    {
        if(DEBUG)
        {
            (new Roomlog())->repairbefore($room,$i);
        }
        $this->wtimerdel("gameroom/updatestate/roomid/{$this->id}/started/1/state/3/seatid/{$room['current']}");
        $this->wtimerdel("gameroom/setTrustRepair/roomid/{$this->id}/seatid/{$room['current']}");
        if (!$room['state']) {
            $this->_error = "room state wrong";
            return false;
        }
        if ($i != $room['current']) {
            $this->_error = "not current,this is {$room['current']}";
            return false;
        }

        $this->lock();

        //数据更新
        $seatkey = "seat$i";

        $seat = $room[$seatkey];

        if ($seat['brepair']) {
            $this->_error = "seat$i have repair";
            return false;
        }
        $room['current'] = $this->getNext($room);
        $seat['brepair']=1;
        $seat['state'] = self::STATE_REPAIR;
        if ($brepair) {
            $cards = $this->cardsredis->hGetAll(self::CARDS_KEY.$this->id);
            $card = $this->sortCard(array_slice($cards, $room['cardscount'], 1));
            $seat['cards'][2] = $card[0];
            $room['cardscount'] += 1;//总牌数
        }
        $this->redis->hMSet(self::INFO_KEY . $this->id, array(
            'current' => $room['current'],
            $seatkey => json_encode($seat),
            'cardscount' => $room['cardscount'],
            'repaircount' => $this->getRepairCount($room) + 1,
        ));

        //$this->setTimer();

        $this->unlock();

        Gateway::$registerAddress = GATEWAYADDRESS;
        $data = array('seatid' => $i,
            'card' => isset($card) ? $card[0] : 0,
            'current' => $room['current'],
            'sex' => $seat['sex'],
        );
        $json = array('type' => 'Room.repair', 'data' => $data);
        Gateway::sendToGroup("game-{$room['id']}", json_encode($json));
        $this->info = null;
        $room = $this->getInfo();
        if(DEBUG)
        {
            (new Roomlog())->repairafter($room,$i);
        }
        if ($this->getRepairCount($room) >= $room['multiplescount']) {
            return $this->setOpenbrand($room);
        } else {
                $this->wtimerset("gameroom/updatestate/roomid/{$room['id']}/started/1/state/3/seatid/{$room['current']}/round/{$room['currentround']}", self::TIMER10 /*+time()*/);
            $this->wtimerset("gameroom/setTrustRepair/roomid/{$room['id']}/seatid/{$room['current']}/round/{$room['currentround']}", self::TIMER5 /*+time()*/);
        }
        return true;
    }

    private function wtimerset($key,$value)
    {
//        $client = stream_socket_client(TEXTSOCKET);
//        if(!$client)exit("can not connect");
//// 模拟超级用户，以文本协议发送数据，注意Text文本协议末尾有换行符（发送的数据中最好有能识别超级用户的字段），这样在Event.php中的onMessage方法中便能收到这个数据，然后做相应的处理即可
//        fwrite($client, '{"type":"add","roomid":"'.$this->id.'","time":"'.$value.'","content":"'.$key.'", "user":"admin", "pass":"******"}'."\n");
//        $response =  fread($client, 5);
//        if($response != "addok")
//        {
//            fwrite($client, '{"type":"add","roomid":"'.$this->id.'","time":"'.$value.'","content":"'.$key.'", "user":"admin", "pass":"******"}'."\n");
//        }
        //RedisDB::factory("wtimer2")->set(DSHOST."/api.php/index/".$key,$value+time());
    }

    private function wtimerdel($key)
    {
//        $client = stream_socket_client(TEXTSOCKET);
//        if(!$client)exit("can not connect");
//// 模拟超级用户，以文本协议发送数据，注意Text文本协议末尾有换行符（发送的数据中最好有能识别超级用户的字段），这样在Event.php中的onMessage方法中便能收到这个数据，然后做相应的处理即可
//        fwrite($client, '{"type":"del","roomid":"'.$this->id.'","content":"'.$key.'", "user":"admin", "pass":"******"}'."\n");
//        $response =  fread($client, 5);
//        if($response != "delok")
//        {
//            fwrite($client, '{"type":"del","roomid":"'.$this->id.'","content":"'.$key.'", "user":"admin", "pass":"******"}'."\n");
//        }
    }

    private function wtimerdelroom()
    {
//        $client = stream_socket_client(TEXTSOCKET);
//        if(!$client)exit("can not connect");
//// 模拟超级用户，以文本协议发送数据，注意Text文本协议末尾有换行符（发送的数据中最好有能识别超级用户的字段），这样在Event.php中的onMessage方法中便能收到这个数据，然后做相应的处理即可
//        fwrite($client, '{"type":"delroom","roomid":"'.$this->id.'", "user":"admin", "pass":"******"}'."\n");
    }

    public function checkTrusInRepair($i, $room)
    {
        $seatkey = "seat$i";
        if (!isset($room[$seatkey])) return;
        $seat = $room[$seatkey];
        $cards = $seat['cards'];
        if (count($cards) < 2)return true;
        if ($seat['trust'] && $seat['state'] == self::STATE_PLAYING) {

            $jnum = $room['joker'] % 100;
            foreach ($cards as $k => $v) {
                if ($v % 100 == $jnum)
                    $cards[$k] = "501";
            }
            $result = $this->getCardType($cards);
            if ($result['type'] < 7 || $result['point'] > 4) {
                $this->setRepair($room, $i, false);
                //大于4点，不补
            } else {
                $this->setRepair($room, $i, true);
                //补牌
            }
        }
        return true;
    }

    public function talk($sound)
    {
        Gateway::$registerAddress = GATEWAYADDRESS;
        $room = $this->getInfo();
        $user = $this->mUser->getInfo();
        $json=array('type'=>'Room.talk','data'=>array('sound'=>$sound,'seatid'=>$user['seatid'],'sex'=>$user['sex']));
        Gateway::sendToGroup("game-{$user['roomid']}",json_encode($json));

        $data['roomid']=$room['sid'];
        $data['actiontype']=1;
        $data['time']=date("Y-m-d H:i:s",time());
        $data['uid']=$user['openid'];
        $data['result']=1;
        db('roomaction')->insert($data);

        return true;
    }

    public function speak($serveid)
    {
        $room = $this->getInfo();
        $user = $this->mUser->getInfo();
        $json=array('type'=>'Room.playrecord','data'=>array('seatid'=>$user['seatid'],'serveid'=>$serveid));
        Gateway::$registerAddress = GATEWAYADDRESS;
        Gateway::sendToGroup("game-{$user['roomid']}", json_encode($json));

        $data['roomid']=$room['sid'];
        $data['actiontype']=2;
        $data['time']=date("Y-m-d H:i:s",time());
        $data['uid']=$user['openid'];
        $data['result']=1;
        db('roomaction')->insert($data);

        return true;
    }

    public function speak1($serveid)
    {
        $access_token = $this->getAccessToken();

        $path = "./weixinrecord/";   //保存路径，相对当前文件的路径
        $outPath = "./php/weixinrecord/";  //输出路径，给show.php 文件用，上一级

        if(!is_dir($path)){
            mkdir($path);
        }

        //微 信上传下载媒体文件
        $url = "http://file.api.weixin.qq.com/cgi-bin/media/get?access_token={$access_token}&media_id={$serveid}";

        $filename = "wxupload_".time().rand(1111,9999).".amr";
        $this->downAndSaveFile($url,$path."/".$filename);
        return;
        $user = $this->mUser->getInfo();
        $json=array('type'=>'Room.playrecord','data'=>array('seatid'=>$user['seatid'],'serveid'=> $outPath.$filename));
        Gateway::$registerAddress = GATEWAYADDRESS;
        Gateway::sendToGroup("game-{$user['roomid']}", json_encode($json));

        return true;
    }

    function downAndSaveFile($url,$savePath){
        ob_start();
        readfile($url);
        $img  = ob_get_contents();
        ob_end_clean();
        $size = strlen($img);
        $fp = fopen($savePath, 'a');
        fwrite($fp, $img);
        fclose($fp);
    }

    //获取Token
    function getAccessToken() {
        //  access_token 应该全局存储与更新，以下代码以写入到文件中做示例
        $data = json_decode(file_get_contents("./access_token.json"));
        if ($data->expire_time < time()) {
            $appid = config("wxconfig.appid");
            $appsecret = config("wxconfig.appsecret");
            $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$appid}&secret={$appsecret}";
            $res = json_decode(httpGet($url));
            $access_token = $res->access_token;
            if ($access_token) {
                $data->expire_time = time() + 7000;
                $data->access_token = $access_token;
                $fp = fopen("./access_token.json", "w");
                fwrite($fp, json_encode($data));
                fclose($fp);
            }
        }
        else {
            $access_token = $data->access_token;
        }
        return $access_token;
    }

    function httpGet($url) {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_TIMEOUT, 500);
        curl_setopt($curl, CURLOPT_URL, $url);

        $res = curl_exec($curl);
        curl_close($curl);

        return $res;
    }

    private function setOpenbrand($room)
    {

        if (!$room['state']) return false;

        Gateway::$registerAddress = GATEWAYADDRESS;

        if ($room['type'] == 1) {
            $zhuang = $room["seat{$room['zhuangid']}"];
            $zhuangcard = $zhuang['cards'];

            $result = array();
            $jnum = $room['joker'] % 100;
            foreach ($zhuangcard as $k => $v) {
                if ($v % 100 == $jnum)
                    $zhuangcard[$k] = "501";
            }
            $result[$room['zhuangid']] = $this->getCardType($zhuangcard);
            $result[$room['zhuangid']]['scores'] = 0;
            for ($i = 1; $i <= self::MAX_POS; ++$i) {
                if (!isset($room["seat$i"]) || $i == $room['zhuangid']) {
                    continue;
                }
                $seat = $room["seat$i"];
                $card = $seat['cards'];
                if (count($card) <2)continue;
                    foreach ($card as $k => $v) {
                        if ($v % 100 == $jnum)
                            $card[$k] = "501";
                    }
                $r = $this->balance($zhuangcard, $card);
                $result[$room['zhuangid']]['scores'] += $r * $seat['multiples'];
                $result[$i] = $this->getCardType($card);
                $result[$i]['scores'] = -$r * $seat['multiples'];
            }

            if (($room['currentround']) % 4 == 0 && $room['currentround'] < $room['round']) {
//                $maxcards = $zhuangcard;
//                for ($i = 1; $i <= self::MAX_POS; ++$i) {
//                    if (!isset($room["seat$i"]) || $i == $room['zhuangid']) {
//                        continue;
//                    }
//                    $r = $this->balance($maxcards, $card);
//                    if ($r < 0) {
//                        $room['zhuangid'] = $i;
//                        $maxcards = $card;
//                    }
//                }

                $maxcard = $room["seat{$room['zhuangid']}"]['cards'];
                $jnum = $room['joker'] % 100;
                foreach ($maxcard as $k => $v) {
                    if ($v % 100 == $jnum)
                        $maxcard[$k] = "501";
                }
                for ($i = 1; $i <= self::MAX_POS; ++$i) {
                    if (!isset($room["seat$i"]) || $i == $room['zhuangid']) {
                        continue;
                    }
                    $seat = $room["seat$i"];
                    if ($seat['carry'] == 1 && ($room['currentround']) % 4 == 0) {
                        $jnum = $room['joker'] % 100;
                        $card = $seat['cards'];
                        if (count($card) < 2) continue;
                        foreach ($card as $k => $v) {
                            if ($v % 100 == $jnum)
                                $card[$k] = "501";
                        }
                        if($this->getCardType($card)['type']==self::CARD_SHUANGGUI)
                        {
                            $room['zhuangid'] = $i;
                            break;
                        }
                        if ($maxcard == null || ($this->balance($card, $maxcard) > 0)) {
                            $room['zhuangid'] = $i;
                            $maxcard = $seat['cards'];
                        }
                    }
                }
            }
        } else if ($room['type'] == 2) {
            $result = array();
            for ($i = 1; $i <= self::MAX_POS; ++$i) {
                if (!isset($room["seat$i"])) {
                    continue;
                }
                $seat1 = $room["seat$i"];
                $card1 = $seat1['cards'];
                if(count($card1)<2)continue;
                $jnum = $room['joker'] % 100;
                foreach ($card1 as $k => $v) {
                    if ($v % 100 == $jnum)
                        $card1[$k] = "501";
                }
                $result[$i] = $this->getCardType($card1);
            }
            for ($i = 1; $i <= self::MAX_POS; ++$i) {
                if (!isset($room["seat$i"])) {
                    continue;
                }
                $seat1 = $room["seat$i"];
                $card1 = $seat1['cards'];
                if(count($card1)<2)continue;
                $jnum = $room['joker'] % 100;
                foreach ($card1 as $k => $v) {
                    if ($v % 100 == $jnum)
                        $card1[$k] = "501";
                }
                for ($j = $i + 1; $j <= self::MAX_POS; ++$j) {
                    if (!isset($room["seat$j"])) {
                        continue;
                    }
                    $seat2 = $room["seat$j"];
                    $card2 = $seat2['cards'];
                    if(count($card2)<2)continue;
                    $jnum = $room['joker'] % 100;
                    foreach ($card2 as $k => $v) {
                        if ($v % 100 == $jnum)
                            $card2[$k] = "501";
                    }
                    $r = $this->balance($card1, $card2);
                    $result[$i]['scores'] += $r * $seat1['multiples'];
                    $result[$j]['scores'] -= $r * $seat2['multiples'];
                }
            }
        }

//        if($room['type']==1) {
//            $maxcard = $room["seat{$room['zhuangid']}"]['cards'];
//            $jnum = $room['joker'] % 100;
//            foreach ($maxcard as $k => $v) {
//                if ($v % 100 == $jnum)
//                    $maxcard[$k] = "501";
//            }
//            for ($i = 1; $i <= self::MAX_POS; ++$i) {
//                if (!isset($room["seat$i"]) || $i == $room['zhuangid']) {
//                    continue;
//                }
//                $seat = $room["seat$i"];
//                if ($seat['carry'] == 1 && ($room['currentround']) % 4 == 0) {
//                    $jnum = $room['joker'] % 100;
//                    $card = $seat['cards'];
//                    if (count($card) < 2) continue;
//                    foreach ($card as $k => $v) {
//                        if ($v % 100 == $jnum)
//                            $card[$k] = "501";
//                    }
//                    if ($maxcard == null || ($this->balance($card, $maxcard) > 0)) {
//                        $room['zhuangid'] = $i;
//                        $maxcard = $seat['cards'];
//                    }
//                }
//            }
//        }

        $this->redis->hMSet(self::INFO_KEY . $this->id, array(
            "zhuangid" => $room['zhuangid'] ,
        ));
        $this->info=null;
        $room=$this->getInfo();
        if(DEBUG)
        {
            (new Roomlog())->openbrand($room);
        }
        foreach ($result as $k => $v) {
            $seat = $room["seat$k"];
            $result[$k]['cards'] = $seat['cards'];
            $result[$k]['zid'] = $room['zhuangid'];
            $result[$k]['state'] = self::STATE_NONE;
            $seat['scores'] += $v['scores'];
            $seat['state'] = self::STATE_NONE;
            $seat['multiples'] = 0;
            $seat['bready']=0;
            $seat['bmultiple']=0;
            $seat['brepair']=0;
            $seat['card'] = null;
            $seat['carry'] = 0;
            $this->redis->hMSet(self::INFO_KEY . $this->id, array(
                "seat$k" => json_encode($seat),
            ));
        }

        $result['currentround'] = $room['currentround'];

        $this->info = null;
        $room = $this->getInfo();

        if(DEBUG)
        {
            (new Roomlog())->openbrandafter($room);
        }

        $data = array();
        $data['roomid'] = $room['sid'];
        $data['roomtype'] = $room['type'];
        $data['roomround'] = $room['round'];
        $data['time'] = date("Y-m-d H:i:s", time());
        for ($i = 1; $i <= self::MAX_POS; ++$i) {
            if (!isset($room["seat$i"])) {
                continue;
            }
            $seat = $room["seat$i"];

            $cardtype['uid']=$seat['uid'];
            $t = $this->getCardType($seat['cards']);
            $cardtype['type']=$t['type'];
            $cardtype['multiples']=$t['multiple'];
            $r = db('cardsrecords')->where($cardtype)->find();
            if($r===null)
            {
                $cardtype['times']=1;
                db('cardsrecords')->insert($cardtype);
            }
            else{
                $r['times']+=1;
                db('cardsrecords')->where($cardtype)->update($r);
            }

            $data["openid$i"] = $seat['uid'];
            $data["headerurl$i"] = $seat['headerurl'];
            $data["seatid$i"] = $seat['seatid'];
            $data["scores$i"] = $seat['scores'];
            $data["name$i"] = $seat['name'];
        }
        if(DEBUG)
        {
            (new Roomlog())->logupdatescores($room,$data);
        }
        $json = array('type' => 'Room.updatescores', 'data' => $data);
        Gateway::sendToGroup("game-{$room['id']}", json_encode($json));

        $json = array('type' => 'Room.openbrand', 'data' => $result);
        Gateway::sendToGroup("game-{$this->id}", json_encode($json));


        $balance = ($room['currentround'] >= $room['round']) ? 1 : 0;
        for ($i = 1; $i <= self::MAX_POS; ++$i) {
            if (!isset($room["seat$i"])) {
                continue;
            }
            $seat = $room["seat$i"];
            if(!$seat['bstart'])
            if (!$seat['bstart'] && $room['currentround'] - $seat['joinround'] >= 1) {
                $this->outroom($i);
                $json = array('type' => 'Room.beout', 'data' => array('seatid' => $i));
                Gateway::sendToUid($seat['uid'], json_encode($json));
            }
        }

        if ($balance) {
            $sid = db('records')->insertGetId($data);
            Gateway::sendToGroup("game-{$this->id}",json_encode(array('type'=>"Room.updaterecordid",'data'=>$sid)));
            $this->info = null;
            $room = $this->getInfo();

            for ($i = 1; $i <= self::MAX_POS; ++$i) {
                if (!isset($room["seat$i"])) {
                    continue;
                }
                $seat = $room["seat$i"];

                $u = new UserModel($seat['uid']);
                $u->save(array(
                    'roomid' => 0,
                    'seatid' => 0,
                ));
            }
            for ($i = 1; $i <= self::MAX_POS; ++$i) {
                $seatkey = "seat$i";

                if (empty($room[$seatkey])) {
                    continue;
                }

                $seat = $room[$seatkey];
                $cids = Gateway::getClientIdByUid($u->getUid());
                if ($cids && count($cids) > 0) {
                    Gateway::leaveGroup(Gateway::getClientIdByUid($u->getUid())[0], "game-{$this->id}");
                    if ($seat['trust']) {
                        $json = array('type' => 'Room.outroom', 'data' => array('seatid' => $i, 'leave' => true));
                        Gateway::sendToUid($seat['uid'], json_encode($json));
                    }
                }
            }
            db('room')->where("id={$room['sid']}")->update(['disbandtime'=>date("Y-m-d H:i:s",time())]);

            //显示战绩，删除房间
            $this->redis->del(self::INFO_KEY . $this->id);
            $this->wtimerdelroom();

        } else {
            $c = $room['currentround']+1;
            $this->wtimerset("gameroom/updatestate/roomid/{$room['id']}/started/1/state/0/round/{$c}", self::TIMER10 + self::TIMER3 /*+time()*/);
            $this->wtimerset("gameroom/setTrustReady/roomid/{$this->getId()}/round/{$c}",self::TIMER5 + self::TIMER3 /*+time()*/);
            $this->redis->hMSet(self::INFO_KEY . $room['id'], array(
                'state' => 0,
                'currentround' => $room['currentround'] + 1,
                'zhuangid' => $room['zhuangid'],
                'cards' => null,
                'joker' => null,
                'cardscount' => 0,
                'current' => 0,
                'repaircount' => 0,
                'multiplescount' => 0,
                'readycount' => 0,
            ));

//            $this->cards=null;
//            $this->info=null;
//            $room=$this->getInfo();
//            for ($i = 1; $i <= self::MAX_POS; ++$i) {
//                if (!isset($room["seat$i"])) {
//                    continue;
//                }
//                $seat=$room["seat$i"];
//                if($seat['trust']) {
//                    $user=(new UserModel($seat['uid']))->getInfo();
//                    $this->ready(false,$user);
//                }
//            }
        }
        if(DEBUG)
        {
            (new Roomlog())->openbrandafter($room);
        }
    }

    public function setTrust($i, $trust)
    {
        $room = $this->getInfo();
        $seatkey = "seat$i";
        $seat = $room[$seatkey];
        $seat['trust'] = $trust;
        $this->redis->hSet(self::INFO_KEY . $room['id'], $seatkey, json_encode($seat));
        Gateway::$registerAddress = GATEWAYADDRESS;
        $json = array('type' => "Room.trust", 'data' => array('seatid'=>$i,'trust'=>$trust));
        Gateway::sendToGroup("game-{$this->id}", json_encode($json));
        if ($trust == '1') {
            $this->updateTrustSeat($seat['state'], $i);
        }
        if(DEBUG)
        {
            $this->info=null;
            $room=$this->getInfo();
            if($trust)
                (new Roomlog())->trust($room,$i);
            else
                (new Roomlog())->canceltrust($room,$i);
        }
        return true;
    }

    private function updateTrustSeat($state, $i = 0)
    {
        $this->info = null;
        $room = $this->getInfo();

        switch ($state) {
            case self::STATE_NONE:
                if($i!=0)
                {
                    $uid=$room["seat$i"]['uid'];
                    $user = new UserModel($uid);
                    $user=$user->getInfo();
                    $this->ready(false,$user);
                }
                break;
            case self::STATE_READY:
                $this->info = null;
                $room = $this->getInfo();
                if($room['started'])
                $this->setmultiple($room, $i, 1);
                break;
            case self::STATE_PLAYING:
                $this->info = null;
                $room = $this->getInfo();
                if ($room['current'] == $i)
                    $this->checkTrusInRepair($i, $room);
                break;
        }
    }

    /**
     * 开始牌局
     * @param $room
     * @throws Exception
     * @throws \Exception
     */
    private function  setStart($room)
    {
        $this->redis->hSet(self::INFO_KEY.$this->id,"readycount",$this->getReadyCount($room));
        $this->wtimerdel("gameroom/updatestate/roomid/{$this->id}/started/0/state/0/round/{$room['currentround']}");
        $this->wtimerdel("gameroom/updatestate/roomid/{$this->id}/started/1/state/0/round/{$room['currentround']}");
        $this->wtimerdel("gameroom/setTrustReady/roomid/{$this->id}/round/{$room['currentround']}");
        Gateway::$registerAddress = GATEWAYADDRESS;
        $num = 1;

        if(DEBUG)
        {
            (new Roomlog())->startroundbefore($room);
        }

        if(!$room['started'])
        {
            $muser = new UserModel($room['owner']);
            $muser->addDiamond(-1*config("roomdiamond.{$room['round']}"));
            Gateway::sendToUid($room['owner'],json_encode(array('type'=>'Game.update','data'=>$muser->getInfo())));
        }
        $this->lock();
        $update['started'] = true;
        $update['state'] = 1;

        if ($room['zhuangid'] == 0) {
            $u = new UserModel($room['owner']);
            $uinfo=$u->getInfo();
            $sid = $uinfo['seatid'];
            if ($sid != 0 && $uinfo['roomid']==$room['id']) {
                $room['zhuangid'] = $sid;
            } else {
                for ($i = 1; $i <= self::MAX_POS; ++$i) {
                    if (!isset($room["seat$i"])) {
                        continue;
                    }
                    $room['zhuangid'] = $i;
                    break;
                }
            }
        }
        $update['zhuangid']=$room['zhuangid'];

        $json = array('type' => 'Room.start', 'data' => array(
            'zhuangid' => $room['zhuangid'],
            'currentround'=>$room['currentround'],
        ));

        Gateway::sendToGroup("game-{$this->id}", json_encode($json));

        if ($room['multiples'] != 1) {

            $this->redis->hMSet(self::INFO_KEY . $this->id, $update);
            $this->unlock();

            $this->wtimerset("gameroom/updatestate/roomid/{$room['id']}/started/1/state/1/round/{$room['currentround']}", self::TIMER10 /*+time()*/);
            $this->wtimerset("gameroom/setTrustMultiple/roomid/{$room['id']}/round/{$room['currentround']}", self::TIMER5 /*+time()*/);
        } else {
            $update['multiplescount'] = 0;
            for ($i = 1; $i <= self::MAX_POS; ++$i) {
                if (!isset($room["seat$i"])) {
                    continue;
                }
                $seat = $room["seat$i"];

                if(DEBUG)
                {
                    (new Roomlog())->setmulbefore($room,$i);
                }

                if(!$seat['bstart'])continue;
                if(!$seat['bready'])continue;
                $seat['multiples'] = 1;
                $seat['bmultiple']=1;
                $seat['state'] = self::STATE_MULTIPLE;
                $update["seat$i"] = json_encode($seat);

                if(DEBUG)
                {
                    (new Roomlog())->setmulafter($room,$i);
                }
            }
            if ($room['type'] != 1) {
                $room['zhuangid'] = 0;  
                $update['zhuangid'] = $room['zhuangid'];
            }
            $this->redis->hMSet(self::INFO_KEY . $this->id, $update);
            $this->unlock();
            $this->info = null;
            $room = $this->getInfo();
            if(DEBUG)
            {
                (new Roomlog())->startround($room);
            }
            $this->fapai($room);

        }
    }

    public function updatestate($room, $started, $state, $seatid)
    {
        if ($started == 0) {
            //如果还没有开始，踢出没有准备的人
            for ($i = 1; $i <= self::MAX_POS; ++$i) {
                if (!isset($room["seat$i"])) {
                    continue;
                }
                $seat = $room["seat$i"];
                if ($seat['state'] == 0) {
                    $this->mUser = new UserModel($seat['uid']);
                    $this->outroom($i);
                }
            }
            $this->info = null;
            $room = $this->getInfo();
            $this->setStart($room);
        } else {
            switch ($state) {
                //基本原则：检查是否超时一次，没有超时就设置超时，超时了就托管
                case self::STATE_NONE:
                case self::STATE_READY:
                    for ($i = 1; $i <= self::MAX_POS; ++$i) {
                        if (!isset($room["seat$i"])) {
                            continue;
                        }
                        $seat = $room["seat$i"];
                        if ($seat['state'] == $state) {
                            if(!$seat['trust']) {
                                if ($seat['bovertime']) {
                                    $this->setTrust($i, true);
                                } else {
                                    $this->setOvertimer($i);
                                    if (!$this->wtimerset("gameroom/updatestate/roomid/{$this->id}/started/1/state/$state/round/{$room['currentround']}", self::TIMER10 /*+time()*/)) {
                                        print_r($this->getError());
                                    }
                                }
                            }
                        }
                    }
                    break;
                case self::STATE_PLAYING:
                    if ($seatid != $room['current']) break;
                    $seat = $room["seat$seatid"];
                    if ($seat['state'] == $state) {
                        if(!$seat['trust']) {
                            if ($seat['bovertime']) {
                                $this->setTrust($seatid, true);
                            } else {
                                $this->setOvertimer($seatid);
                                $this->wtimerset("gameroom/updatestate/roomid/{$this->id}/started/1/state/$state/seatid/$seatid/round/{$room['currentround']}", self::TIMER10 /*+time()*/);
                            }
                        }
                    }
                    break;
            }
        }
        return true;
    }

    public function setmultiple($room, $i, $multiple)
    {
        if(DEBUG)
        {
            (new Roomlog())->setmulbefore($room,$i);
        }
        Gateway::$registerAddress = GATEWAYADDRESS;

        if ($multiple > $room['multiples']) {
            $this->_error = 'multiples must small room multiples';
            return false;
        }

        //加锁
        $this->lock();

        //数据更新
        $seatkey = "seat" . $i;
        $seat = $room[$seatkey];
        $seat['state'] = self::STATE_MULTIPLE;
        $seat['multiples'] = $multiple;
        $seat['bmultiple']=1;
        $this->redis->hMSet(self::INFO_KEY . $this->id, array(
            $seatkey => json_encode($seat),
        ));
        $this->unlock();
        $data = array('seatid' => $i, 'multiples' => $seat['multiples']);
        $json = array('type' => 'Room.selmultiples', 'data' => $data);
        Gateway::sendToGroup("game-{$room['id']}", json_encode($json));


        $this->info = null;
        $room = $this->getInfo();
        if(DEBUG)
        {
            (new Roomlog())->setmulafter($room,$i);
        }
        if ($this->getMultiplesCount($room) >= $room['readycount']) {
            $this->fapai($room);
        }
        return true;
    }

    private function fapai($room)
    {
        $this->redis->hSet(self::INFO_KEY . $this->id, "multiplescount", $this->getMultiplesCount($room));

        $this->wtimerdel("gameroom/updatestate/roomid/{$room['id']}/started/1/state/1/round/{$room['currentround']}");
        $this->wtimerdel("gameroom/setTrustMultiple/roomid/{$room['id']}/round/{$room['currentround']}");
        $num = 0;
        $cards = $this->makeCards();

        $this->cardsredis->hMSet(self::CARDS_KEY.$this->id,$cards);

        $joker = null;
        if ($room['jcard'] == 1) {
            $cardnum = 53;
            do {
                $joker = $this->sortCard(array_slice($cards, $cardnum, 1));
                --$cardnum;
            } while ($joker[0] > 500);
        }

        $update['joker'] = $joker[0];

        for ($i = 1; $i <= self::MAX_POS; ++$i) {
            if (!isset($room["seat$i"])) {
                continue;
            }
            $seat = $room["seat$i"];
            if ($seat['multiples'] == 0) continue;
            if(!$seat['bstart'])continue;
            //更新所有人状态
            $seat['state'] = self::STATE_PLAYING;
            $seat['cards'] = $this->sortCard(array_slice($cards, $num * 2, 2));
            $update["seat$i"] = json_encode($seat);
            $room["seat$i"] = ($seat);
            $num++;
        }
        $room['current'] = $room['zhuangid'];

        $room['current'] = $this->getNext($room);
        if ($room['type'] == 2) {
            for ($r = 1; $r < $room['currentround']; ++$r) {
                $room['current'] = $this->getNext($room);
            }
        }
        $update['current'] = $room['current'];

        for ($i = 1; $i <= self::MAX_POS; ++$i) {
            if (!isset($room["seat$i"])) {
                continue;
            }
            $seat = $room["seat$i"];
            $data = array(
                'cards' => $seat['cards'],
                'current' => $room['current'],
                'state' => 1,
                'seatstate' => $seat['state'],
                'joker' => $joker[0],
                'zhuangid' => $room['zhuangid'],
            );
            $json = array('type' => 'Room.fapai', 'data' => $data);
            Gateway::sendToUid($seat['uid'], json_encode($json));
            //人数+1

        }

        $update['state'] = 1;
        $update['cardscount'] = $num * 2;

        $this->redis->hMSet(self::INFO_KEY . $this->id, $update);
        if(DEBUG)
        {
            $this->info=null;
            $room=$this->getInfo();
            (new Roomlog())->fapai($room);
        }
        $this->wtimerset("gameroom/updatestate/roomid/{$room['id']}/started/1/state/3/seatid/{$room['current']}/round/{$room['currentround']}", self::TIMER10 /*+time()*/);
        $this->wtimerset("gameroom/setTrustRepair/roomid/{$room['id']}/seatid/{$room['current']}/round/{$room['currentround']}", self::TIMER5 /*+time()*/);
        return true;
    }

    /**
     * 获取下次出手玩家
     * @param array $room
     * @return int
     */
    public function getNext($room)
    {
        if (!$room) {
            return 0;
        }

        $actives = array();
        for ($i = 1; $i <= self::MAX_POS; ++$i) {
            $seatkey = "seat$i";
            if (!isset($room[$seatkey])) {
                continue;
            }

            $seat = $room[$seatkey];
            if ($seat['state'] == self::STATE_PLAYING) {
                $actives[$i] = 1;
            }
        }
        if (count($actives) < 2) {
            return 0;
        }

        $start = $current = $room['current'];
        do {
            if (++$current > self::MAX_POS) {
                $current = 1;
            }

            if ($current == $start) {
                break;
            }

            if (!isset($actives[$current])) {
                continue;
            }
            $seatkey = "seat$current";
            $seat = $room[$seatkey];
            if ($seat['brepair'])
                continue;

            return $current;
        } while (true);

        return 0;
    }

    public function updategame($round, $type, $jcard, $multiples)
    {
        $user = $this->mUser->getInfo();
        $room = $this->getInfo();
        if ($user["openid"] != $room["owner"]) {
            $this->_error = "no room owner";
            return false;
        }
        $room['round'] = $round;//局数
        $room['type'] = $type;
        $room['jcard'] = $jcard;
        $room['multiples'] = $multiples;
        $room['readycount'] = 0;
        for ($i = 1; $i <= self::MAX_POS; ++$i) {
            $seatkey = "seat$i";
            if (!isset($room[$seatkey])) {
                continue;
            }
            $seatkey = "seat$i";
            $room[$seatkey]["state"] = self::STATE_NONE;
            $room[$seatkey] = json_encode($room[$seatkey]);
        }
        $this->redis->hMset(self::INFO_KEY . $room['id'], $room);
        Gateway::$registerAddress = GATEWAYADDRESS;
        $json = array("type" => "Room.updategame", "data" => array('round' => $round,//局数
            'type' => $type,
            'jcard' => $jcard,
            'multiples' => $multiples,));
        Gateway::sendToGroup("game-{$this->id}", json_encode($json));
        return true;
    }

    /**
     * 生成牌列表
     * @return array
     */
    private function makeCards()
    {
        if ($this->cards == null) {
            $this->cards = array();
            for ($i = 1; $i <= 4; ++$i) {
                for ($j = 1; $j <= 13; ++$j) {
                    $this->cards[] = $i * 100 + $j;
                }
            }
            $this->cards[52] = 501;
            $this->cards[53] = 502;

            shuffle($this->cards);
        }
        return $this->cards;
    }

    /**
     * 排序(从大到小排)
     * @param array $cards
     * @return array
     */
    private function sortCard($cards)
    {
        $list = array();
        foreach ($cards as $card) {
            $value = $card % 100;
            $list[$card] = $value;
        }

        arsort($list);

        return array_keys($list);
    }

    /**
     * 对比牌
     * @param array $c1
     * @param array $c2
     * @return int
     */
    private function compareCard($cards1, $cards2)
    {
        $c1 = $this->getCardInfo($cards1);
        $c2 = $this->getCardInfo($cards2);
        $win = 0;
        if ($c1['type'] > $c2['type']) {
            $win = 1;
        } else if ($c2['type'] > $c1['type']) {
            $win = 2;
        } else {
            if (in_array($c1['type'], array(1, 3, 4, 5))) {
                $values1 = $c1['values'];
                $values2 = $c2['values'];
            } else {
                $values1 = array($c1['max'], $c1['min']);
                $values2 = array($c2['max'], $c2['min']);
            }

            //从最大牌开始往下比
            foreach ($values1 as $k => $v) {
                if ($v > $values2[$k]) {
                    $win = 1;
                    break;
                } else if ($values2[$k] > $v) {
                    $win = 2;
                    break;
                }
            }

            //相同的就是对面赢
            if (!$win) {
                $win = 2;
            }
        }

        return $win;
    }

    /**
     * 获取牌型
     * @param array $cards
     * @return array
     */
    private function getCardInfo($cards)
    {
        $colorCounts = array();
        $valueCounts = array();
        $values = array();
        foreach ($cards as $card) {
            $color = floor($card / 100);
            $value = $card % 100;
            $colorCounts[$color] += 1;
            $valueCounts[$value] += 1;
            $values[] = $value;
        }

        if (count($valueCounts) == 1) {//炸弹
            $type = 6;
            $min = $max = $values[0];
        } else if (count($colorCounts) == 1) {//共花 or 同花顺
            if ($values[0] - 1 == $values[1] && $values[1] - 1 == $values[2]) {
                $type = 5;
                $max = $values[0];
                $min = $values[2];
            } else {
                $type = 4;
                $max = $values[0];
                $min = $values[2];
            }
        } else if (count($valueCounts) == 3 && $values[0] - 1 == $values[1] && $values[1] - 1 == $values[2]) {//顺子
            $type = 3;
            $max = $values[0];
            $min = $values[2];
        } else if (count($valueCounts) == 2) {//对子
            $type = 2;
            $c1 = $values[0];
            $c3 = $values[2];
            $max = $valueCounts[$c1] > 1 ? $c1 : $c3;
            $min = $max == $c1 ? $c3 : $c1;
        } else {//散牌
            $type = 1;
            $max = $values[0];
            $min = $values[1];
        }

        return array(
            'type' => $type,
            'min' => $min,
            'max' => $max,
            'values' => $values,
        );
    }

    public function feed()
    {
        $room = $this->getInfo();
        $data['uid']=$this->uid;
        $data['roomid']=$this->id;
        $data['time']=date('Y-m-d H:i:s',time());
        $data['roominfo']=json_encode($room);
        db('feed_test')->insert($data);
    }
}